package com.yundingai.utils;

import com.yundingai.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @Author HuangZhengmin
 * @desc  MinIO 的工具类
 * @Date 2025/7/16 14:46
 * @Version 1.0
 */
@Slf4j
@Component
public class MinIOUtil {

  @Resource
  private MinioConfig minioConfig;

  @Resource
  private MinioClient minioClient;

  /**
   * 查看存储bucket是否存在
   *
   * @param bucketName 存储桶名称
   * @return boolean
   */
  public Boolean bucketExists(String bucketName) {
    Boolean found;
    try {
      found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
    return found;
  }

  /**
   * 创建存储bucket
   *
   * @param bucketName 存储桶名称
   * @return Boolean
   */
  public Boolean makeBucket(String bucketName) {
    try {
      minioClient.makeBucket(MakeBucketArgs.builder()
              .bucket(bucketName)
              .build());
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }

  /**
   * 删除存储bucket
   *
   * @param bucketName 存储桶名称
   * @return Boolean
   */
  public Boolean removeBucket(String bucketName) {
    try {
      minioClient.removeBucket(RemoveBucketArgs.builder()
              .bucket(bucketName)
              .build());
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }

  /**
   * 获取全部bucket
   *
   * @return 存储桶列表
   */
  public List<Bucket> getAllBuckets() {
    try {
      return minioClient.listBuckets();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 文件上传
   *
   * @param file 文件
   * @return 文件对象名称
   */
  public String upload(MultipartFile file) {
    String originalFilename = file.getOriginalFilename();

    System.out.println(originalFilename);

    if (!StringUtils.hasText(originalFilename)) {
      throw new RuntimeException();
    }

    //使用UUID.randomUUID()生成一个唯一的标识符，并加上原始文件名的后缀部分，生成新的文件名。
    String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
    //使用当前日期生成文件路径前缀，格式为yyyy/MM/dd
    String prefix = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
    //将前缀和文件名拼接起来，生成完整的文件对象名称
    String objectName = prefix + "/" + fileName;
    try {
      PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(objectName)
              .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
      // 文件名称相同会覆盖
      minioClient.putObject(objectArgs);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
    return objectName;
  }

  /**
   * 预览图片
   *
   * @param fileName 文件名称
   * @return 文件预览链接
   */
  public String preview(String fileName) {
    // 查看文件地址
    GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
            .builder()
            .bucket(minioConfig.getBucketName())
            .object(fileName).method(Method.GET).build();
    try {
      String url = minioClient.getPresignedObjectUrl(build);
      return url;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 文件下载
   *
   * @param fileName 文件名称
   * @param res      response
   */
  public void download(String fileName, HttpServletResponse res) {
    GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName())
            .object(fileName).build();
    try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
      byte[] buf = new byte[1024];
      int len;
      try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
        while ((len = response.read(buf)) != -1) {
          os.write(buf, 0, len);
        }
        os.flush();
        byte[] bytes = os.toByteArray();
        res.setCharacterEncoding("utf-8");
        res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
        try (ServletOutputStream stream = res.getOutputStream()) {
          stream.write(bytes);
          stream.flush();
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 查看文件对象
   *
   * @return 存储bucket内文件对象信息
   */
  public List<Item> listObjects() {
    Iterable<Result<Item>> results = minioClient.listObjects(
            ListObjectsArgs.builder().bucket(minioConfig.getBucketName()).build());
    List<Item> items = new ArrayList<>();
    try {
      for (Result<Item> result : results) {
        items.add(result.get());
      }
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
    return items;
  }

  /**
   * 删除
   *
   * @param fileName 文件名称
   * @return 是否删除成功
   */
  public boolean remove(String fileName) {
    try {
      minioClient.removeObject(RemoveObjectArgs.builder()
              .bucket(minioConfig.getBucketName())
              .object(fileName)
              .build());
    } catch (Exception e) {
      return false;
    }
    return true;
  }

}

